package cn.com.ccxe.core.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wltea.analyzer.lucene.IKQueryParser;

import cn.com.ccxe.core.crawl.MonitorField;
import cn.com.ccxe.core.entity.Article;
import cn.com.ccxe.core.entity.Keyword;
import cn.com.ccxe.core.util.Configurations;

public class Searcher {

	private static final Logger logger = LoggerFactory.getLogger(Searcher.class);
	private static Directory directory = null;
	private static Searcher instance;
	private static String DIRECTORY_PATH = Configurations.getString("index.path","/directory");
	
	private Searcher() {
		this(DIRECTORY_PATH);
	}

	private Searcher(String path) {
		File directoryHome = new File(path);
		try {
			directory = new NIOFSDirectory(directoryHome);
			logger.info("directory fileExists " + directory.fileExists("segments_1a"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	public List<Article> search(List<Keyword> keywords, int moduleId) throws IOException {
		logger.info(arrayToString(keywords));
		BooleanQuery query = new BooleanQuery();
		Query query1 = new TermQuery(new Term(MonitorField.MODULE_ID.name(), String.valueOf(moduleId)));
		// Query query1 =
		// IKQueryParser.parse(SearchContext.FieldName.MODULE_ID.get(),
		// String.valueOf(moduleId));
		query.add(query1, BooleanClause.Occur.MUST);
		query.setMinimumNumberShouldMatch(1);
		injectQueryItem(query, BooleanClause.Occur.SHOULD, keywords);
		return createSearch(query);
	}

	public List<Article> search(String[] keywords, int moduleId) throws IOException {
		Query query1 = IKQueryParser.parse(MonitorField.MODULE_ID.name(), String.valueOf(moduleId));
		BooleanQuery query = new BooleanQuery();
		query.add(query1, BooleanClause.Occur.MUST);
		query.setMinimumNumberShouldMatch(1);
		injectQueryItem(query, BooleanClause.Occur.SHOULD, keywords);
		return createSearch(query);
	}

	private List<Article> createSearch(BooleanQuery query) throws CorruptIndexException, IOException {
		IndexSearcher isearcher = null;
		try {
			// logger.info("directory:"+directory);
			// 实例化搜索器
			isearcher = new IndexSearcher(directory);

			// 搜索相似度最高的50条记录
			TopDocs topDocs = isearcher.search(query, 500);
			// 输出结果
			ScoreDoc[] scoreDocs = topDocs.scoreDocs;
			List<Article> list = new ArrayList<Article>();
			Set<Article> set = new HashSet<Article>();
			for (int i = 0; i < scoreDocs.length; i++) {
				Document targetDoc = isearcher.doc(scoreDocs[i].doc);
				String title = targetDoc.get(MonitorField.TITLE.name());
				if ("".equals(title)) {
					continue;
				}
				Article article = new Article();
				article.setModuleId(Integer.valueOf(targetDoc.get(MonitorField.MODULE_ID.name())));
				article.setTitle(title);
				article.setUrl(targetDoc.get(MonitorField.URL.name()));
				article.setReleaseDate(targetDoc.get(MonitorField.RELEASE_DATE.name()));
				set.add(article);

			}
			list.addAll(set);
			return list;
		} finally {
			if (isearcher != null) {
				isearcher.close();
			}
		}
	}

	public static Searcher getInstance() {
		if (instance == null) {
			instance = new Searcher();
			return instance;
		}
		return instance;
	}

	public static Searcher getInstance(String path) {
		if (instance == null) {
			instance = new Searcher(path);
			return instance;
		}
		return instance;
	}

	public void close() {
		if (directory != null) {
			try {
				directory.close();
			} catch (IOException e) {
				logger.info("关闭索引库失败！");
				e.printStackTrace();
			}
		}
	}

	private void injectQueryItem(BooleanQuery query, Occur occur, List<Keyword> keywords) {
		if(keywords == null || keywords.size() == 0) {
			return;
		}
		for (Keyword keyword : keywords) {
			Query q = new TermQuery(new Term(MonitorField.TITLE.name(), keyword.getText()));
			query.add(q, occur);
		}
	}

	private void injectQueryItem(BooleanQuery query, Occur occur, String[] keywords) {
		for (String keyword : keywords) {
			Query q = new TermQuery(new Term(MonitorField.TITLE.name(), keyword));
			query.add(q, occur);
		}
	}

	public String arrayToString(String[] strs) {
		StringBuilder sb = new StringBuilder();
		for (String str : strs) {
			sb.append(str);
			sb.append("");
		}
		return sb.toString();
	}

	public String arrayToString(List<Keyword> list) {
		if (list == null) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (Keyword k : list) {
			sb.append(k.getText());
		}
		return sb.toString();
	}

	public static void main(String[] args) throws IOException {
		Searcher searcher = Searcher.getInstance();
		List<Keyword> list = new ArrayList<Keyword>();
		// String [] array = new
		// String[]{"中国","日本","国际","世界","中国石油","海南航空","中","可口可乐"};
		String[] array = new String[] { "基金" };
		for (int i = 0; i < array.length; i++) {
			Keyword k = new Keyword();
			k.setText(array[i]);
			list.add(k);
		}
		List<Article> as = searcher.search(list,21);
		for (Article article : as) {
			System.out.println(article);
		}
	}

}
